
/* Welcome to the ECU Reader project. This sketch uses the Canbus library.
It requires the CAN-bus shield for the Arduino. This shield contains the MCP2515 CAN controller and the MCP2551 CAN-bus driver.
A connector for an EM406 GPS receiver and an uSDcard holder with 3v level convertor for use in data logging applications.
The output data can be displayed on a serial LCD.

The SD test functions requires a FAT16 formated card with a text myFile of WRITE00.TXT in the card.


SK Pang Electronics www.skpang.co.uk
v4.0 04-03-12 Updated for Arduino 1.0
v3.0 21-02-11  Use library from Adafruit for sd card instead.

*/

#include <SdFat.h>
#include <SdFatUtil.h>
#include <SoftwareSerial.h>
#include <Canbus.h>

//File myFile;


Sd2Card card;
SdVolume volume;
SdFile root;
SdFile myFile;


/* Define Joystick connection */
#define UP     A1
#define RIGHT  A2
#define DOWN   A3
#define CLICK  A4
#define LEFT   A5

  
char buffer[512];  //Data will be temporarily stored to this buffer before being written to the myFile
char tempbuf[15];
char lat_str[14];
char lon_str[14];

int read_size=0;   //Used as an indicator for how many characters are read from the myFile
int count=0;       //Miscellaneous variable

int D10 = 10;

int LED2 = 8;
int LED3 = 7;

const int chipSelect = 9;


SoftwareSerial mySerial =  SoftwareSerial(5, 4);


#define GPSRATE 4800


// GPS parser for 406a
#define BUFFSIZ 90 // plenty big
//char buffer[BUFFSIZ];
char *parseptr;
char buffidx;
uint8_t hour, minute, second, year, month, date;
uint32_t latitude, longitude;
uint8_t groundspeed, trackangle;
char latdir, longdir;
char status;
uint32_t waypoint = 0;
   char *name;
#define error(s) error_P(PSTR(s))

void error_P(const char* str) {
  PgmPrint("error: ");
  SerialPrintln_P(str);
  

  Serial.print("SD error");
  
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
   
  }
  while(1);
}


//byte PIDS[4];
//String PIDDesc[4];

void setup() {
delay(2000);
  pinMode(10, OUTPUT);
 
  mySerial.begin(GPSRATE);
  pinMode(LED2, OUTPUT); 
  pinMode(LED3, OUTPUT); 
 
  digitalWrite(LED2, LOW);
  pinMode(UP,INPUT);
  pinMode(DOWN,INPUT);
  pinMode(LEFT,INPUT);
  pinMode(RIGHT,INPUT);
  pinMode(CLICK,INPUT);

  digitalWrite(UP, HIGH);       /* Enable internal pull-ups */
  digitalWrite(DOWN, HIGH);
  digitalWrite(LEFT, HIGH);
  digitalWrite(RIGHT, HIGH);
  digitalWrite(CLICK, HIGH);
  
  
  Serial.begin(115200);
  Serial.println("ECU Reader");  /* For debug use */
  
  if(Canbus.init(CANSPEED_1000))  /* Initialise MCP2515 CAN controller at the specified speed */
  {
    Serial.println("CAN Init ok");
  } else
  {
    Serial.println("Can't init CAN");
  } 
  Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
    if (!card.init(SPI_HALF_SPEED,9)) error("card.init failed");
  
  // initialize a FAT volume
  if (!volume.init(&card)) error("volume.init failed");
  
  // open the root directory
  if (!root.openRoot(&volume)) error("openRoot failed");

  // create a new myFile
  name = "WRITE00.TXT";
  for (uint8_t i = 0; i < 100; i++) {
    name[5] = i/10 + '0';
    name[6] = i%10 + '0';

    if (myFile.open(&root, name, O_CREAT | O_EXCL | O_WRITE)) break;
//    if (myFile.open(&root,name, O_RDWR | O_CREAT | O_AT_END)) break;
  }
//  if (!myFile.isOpen()) error ("myFile.create");
  Serial.print("Writing to: ");
  Serial.println(name);
  // write header
//  myFile.writeError = 0;
           
          
}



void loop() {
 
// while(1){
//   while (mySerial.available()) {
//     // get the new byte:
//     char inChar = (char)mySerial.read(); 
//    // add it to the inputString:
//    Serial.write(inChar);
//  }
// 
// delay(10); 
// }

if (!myFile.open(&root,name, O_RDWR | O_CREAT | O_AT_END)){
  myFile.print("Writing");
  Serial.println("Reading GPS");
     read_gps();
     
     myFile.print(waypoint++);
     myFile.print(',');
     myFile.print(lat_str);
     myFile.print(',');
     myFile.print(lon_str);
     myFile.print(',');
      
     Serial.print(waypoint++);
     Serial.print(',');
     Serial.print(lat_str);
     Serial.print(',');
     Serial.println(lon_str);
 
     digitalWrite(LED3, HIGH);
  if(Canbus.ecu_req(ENGINE_RPM,buffer) == 1)          /* Request for engine RPM */
      {
        
              Serial.print("ENGINE_RPM:");
              Serial.print(buffer);                         
              myFile.print("ENGINE_RPM:");
              myFile.print(buffer);

            }   
              myFile.print(',');
  if(Canbus.ecu_req(VEHICLE_SPEED,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("VEHICLE_SPEED:");
              Serial.print(buffer);                         
              myFile.print("VEHICLE_SPEED:");
              myFile.print(buffer);
            }   
              myFile.print(',');
  if(Canbus.ecu_req(ENGINE_COOLANT_TEMP,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("ENGINE_COOLANT_TEMP:");
              Serial.print(buffer);                         
              myFile.print("ENGINE_COOLANT_TEMP:");
              myFile.print(buffer);

            }   
              myFile.print(',');
  if(Canbus.ecu_req(THROTTLE,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("THROTTLE:");
              Serial.print(buffer);                         
              myFile.print("THROTTLE:");
              myFile.print(buffer);

            }   
              myFile.print(',');          
  if(Canbus.ecu_req(ENGINERUNTIME,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("ENGINERUNTIME:");
              Serial.print(buffer);                         
              myFile.print("ENGINERUNTIME:");
              myFile.print(buffer);
            }               
              myFile.print(',');

  if(Canbus.ecu_req(ACCELPOSD,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("ACCELPOSD:");
              Serial.print(buffer);                         
              myFile.print("ACCELPOSD:");
              myFile.print(buffer);
            }               
              myFile.print(',');
  if(Canbus.ecu_req(ACCELPOSE,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("ACCELPOSE:");
              Serial.print(buffer);                         
              myFile.print("ACCELPOSE:");
              myFile.print(buffer);
            }               
              myFile.print(',');     
       if(Canbus.ecu_req(ACCELPOSF,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("ACCELPOSF:");
              Serial.print(buffer);                         
              myFile.print("ACCELPOSF:");
              myFile.print(buffer);
            }               
              myFile.print(',');     
  if(Canbus.ecu_req(FUELLEVELINPUT,buffer) == 1)          /* Request for engine RPM */
      {
        
             Serial.print("FUELLEVELINPUT:");
              Serial.print(buffer);                         
              myFile.print("FUELLEVELINPUT:");
              myFile.print(buffer);
            }               
              myFile.print(',');              
  if(Canbus.ecu_req(ABS_LOAD_VAL,buffer) == 1)          /* Request for engine ABS Load */
      {
        
             Serial.print("ABS_LOAD_VAL:");
              Serial.print(buffer);                         
              myFile.print("ABS_LOAD_VAL:");
              myFile.print(buffer);
            }               
              myFile.print(',');              
  if(Canbus.ecu_req(LOAD_VALUE,buffer) == 1)          /* Request for engine ABS Load */
      {
        
             Serial.print("ENGINE_LOAD_VALUE:");
              Serial.print(buffer);                         
              myFile.print("ENGINE_LOAD_VALUE:");
              myFile.print(buffer);
            }               
              myFile.print(',');              
//  if(Canbus.ecu_req(MAN_PRESSURE,buffer) == 1)          /* Request for engine Man Pressure */
//      {
//        
//             Serial.print("MAN_PRESSURE:");
//              Serial.print(buffer);                         
//              myFile.print("MAN_PRESSURE:");
//              myFile.print(buffer);
//            }               
//              myFile.print(',');              
//  if(Canbus.ecu_req(BARO_PRESSURE,buffer) == 1)          /* Request for engine Baro Pressure */
//      {
//        
//             Serial.print("BARO_PRESSURE:");
//              Serial.print(buffer);                         
//              myFile.print("BARO_PRESSURE:");
//              myFile.print(buffer);
//            }               
//              myFile.print(',');              
  if(Canbus.ecu_req(FUEL_RATE,buffer) == 1)          /* Request for engine Baro Pressure */
      {
        
             Serial.print("FUEL_RATE:");
              Serial.print(buffer);                         
              myFile.print("FUEL_RATE:");
              myFile.print(buffer);
            }               
              myFile.print(',');              



       digitalWrite(LED3, LOW); 
     
      
       myFile.println();  
  

 
           myFile.close();
}
Serial.print("Loop: ");
Serial.println(millis());
  }
   
void read_gps(void)
{
 uint32_t tmp;

  unsigned char i;
  unsigned char exit = 0;
  
  
  while( exit == 0)
  { 
    
   readline();
 
  // check if $GPRMC (global positioning fixed data)
   if (strncmp(buffer, "$GPRMC",6) == 0) {
     
        digitalWrite(LED2, HIGH);
        
        // hhmmss time data
        parseptr = buffer+7;
        tmp = parsedecimal(parseptr); 
        hour = tmp / 10000;
        minute = (tmp / 100) % 100;
        second = tmp % 100;
        
        parseptr = strchr(parseptr, ',') + 1;
        status = parseptr[0];
        parseptr += 2;
          
        for(i=0;i<11;i++)
        {
          lat_str[i] = parseptr[i];
        }
        lat_str[12] = 0;
      //  Serial.println(" ");
      //  Serial.println(lat_str);
       
        // grab latitude & long data
        latitude = parsedecimal(parseptr);
        if (latitude != 0) {
          latitude *= 10000;
          parseptr = strchr(parseptr, '.')+1;
          latitude += parsedecimal(parseptr);
        }
        parseptr = strchr(parseptr, ',') + 1;
        // read latitude N/S data
        if (parseptr[0] != ',') {
          
          latdir = parseptr[0];
        }
        
        // longitude
        parseptr = strchr(parseptr, ',')+1;
      
        for(i=0;i<12;i++)
        {
          lon_str[i] = parseptr[i];
        }
        lon_str[13] = 0;
        
        //Serial.println(lon_str);
   
        longitude = parsedecimal(parseptr);
        if (longitude != 0) {
          longitude *= 10000;
          parseptr = strchr(parseptr, '.')+1;
          longitude += parsedecimal(parseptr);
        }
        parseptr = strchr(parseptr, ',')+1;
        // read longitude E/W data
        if (parseptr[0] != ',') {
          longdir = parseptr[0];
        }
        
    
        // groundspeed
        parseptr = strchr(parseptr, ',')+1;
        groundspeed = parsedecimal(parseptr);
    
        // track angle
        parseptr = strchr(parseptr, ',')+1;
        trackangle = parsedecimal(parseptr);
    
        // date
        parseptr = strchr(parseptr, ',')+1;
        tmp = parsedecimal(parseptr); 
        date = tmp / 10000;
        month = (tmp / 100) % 100;
        year = tmp % 100;
        
       
        digitalWrite(LED2, LOW);
        exit = 1;
       }
       
  }   

}

      
      


void readline(void) {
  char c;
  
  buffidx = 0; // start at begninning
  while (1) {
      c=mySerial.read();
      if (c == -1)
        continue;
  //    Serial.print(c);
      if (c == '\n')
        continue;
      if ((buffidx == BUFFSIZ-1) || (c == '\r')) {
        buffer[buffidx] = 0;
        return;
      }
      buffer[buffidx++]= c;
  }
}
uint32_t parsedecimal(char *str) {
  uint32_t d = 0;
  
  while (str[0] != 0) {
   if ((str[0] > '9') || (str[0] < '0'))
     return d;
   d *= 10;
   d += str[0] - '0';
   str++;
  }
  return d;
}


